package cn.topcodes.tcsf.wechat.service;

import cn.topcode.unicorn.utils.FileUtil;
import cn.topcode.unicorn.utils.PropertyConfigurer;
import cn.topcode.unicorn.utils.StringUtil;
import cn.topcode.unicorn.utils.UuidUtil;
import it.sauronsoftware.jave.Encoder;
import it.sauronsoftware.jave.EncoderException;
import it.sauronsoftware.jave.MultimediaInfo;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StreamUtils;

import java.io.*;

/**
 * 获取微信永久素材 服务
 * @author xw
 * @date 2017-12-30 23:29:17
 */
@Component
public class WechatFileService {

    @Autowired
    private PropertyConfigurer prop;

    public static final String FILE_TYPE_PICTURE = "picture";

    public static final String FILE_TYPE_VOICE = "voice";

    public static final String FILE_TYPE_VIDEO = "video";

    public static final String FILE_TYPE_THUMB = "thumb";

    public static final String FILE_TYPE_HEAD_IMAGE = "headImage";

    public static final String BACKUP_SUFFIX = ".bak";



    public String getBasePath() {
        return prop.getProperty("file.folder");
    }

    public String getVideoStoragePath() {
        return getBasePath() + "/video";
    }

    public String getVoiceStoragePath() {
        return getBasePath() + "/voice";
    }

    public String getPictureStoragePath() {
        return getBasePath() + "/picture";
    }

    public String getHeadImagePath() { return getBasePath() + "/headImage"; }

    /**
     * 文件重命名
     * @param file
     * @param newName
     */
    public File rename(File file, String newName) {
        String parent = file.getParent();
        String name = file.getName();
        String suffix = this.getSuffix(name);
        String newFileName = null;

        if (StringUtil.isBlank(newName)) {
            newFileName = UuidUtil.getUUID();
        } else if(StringUtil.isNotBlank(newName) && !newName.equals(name)) {
            newFileName = newName;
        }
        try {
            File dest = new File(parent, newFileName + suffix);
            FileUtils.moveFile(file, dest);
            return dest;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 创建一个文件, 文件名UUID生成
     * @param parent    父路径
     * @param suffix    文件后缀
     * @return
     */
    public File createFile(String parent, String suffix) {
        if (StringUtil.isNotBlank(parent)
                && StringUtil.isNotBlank(suffix)) {
            File file = new File(parent, UuidUtil.getUUID() + suffix);
            return file;
        }
        return null;
    }

    /**
     * 删除一个文件
     * @param type      文件类型: picture(图片), voice(语音), video(视频), thumb(视频缩略图)
     * @param filename
     */
    public void deleteFile(String type, String filename) {
        if (StringUtil.isBlank(type)) {
            System.err.println("请选择需要删除的文件类型: 图片、语音、视频、缩略图");
            return;
        }
        File file = this.getFile(type, filename);
        if (file != null) {
            if (file.exists()) {
                file.delete();
            } else {
                System.err.println("没有找到该文件");
                return;
            }
        }
    }

    /**
     * 获取语音和视频文件播放时长
     * @param file
     * @return
     */
    public long getDuration(File file) {
        Encoder encoder = new Encoder();
        MultimediaInfo m = null;
        try {
            m = encoder.getInfo(file);
        } catch (EncoderException e) {
            e.printStackTrace();
        }
        return m.getDuration();
    }

    /**
     * 获取一个文件
     * @param type
     * @param filename
     * @return
     */
    public File getFile(String type, String filename) {
        if (StringUtil.isNotBlank(type)
                && StringUtil.isNotBlank(filename)) {
            String parent = null;
            if (FILE_TYPE_PICTURE.equals(type)) {
                parent = this.getPictureStoragePath();
            } else if (FILE_TYPE_VOICE.equals(type)) {
                parent = this.getVoiceStoragePath();
            } else if (FILE_TYPE_VIDEO.equals(type) || FILE_TYPE_THUMB.equals(type)) {
                parent = this.getVideoStoragePath();
            } else if (FILE_TYPE_HEAD_IMAGE.equals(type)) {
                parent = this.getHeadImagePath();
            }
            if (StringUtil.isNotEmpty(parent)) {
                File file = new File(parent, filename);
                return file;
            }
        }
        return null;
    }

    /**
     * 通过url获取文件名
     * @param url
     * @param features
     * @return
     */
    public String getNameByUrl(String url, String features) {
        if (StringUtil.isNotBlank(url)
                && StringUtil.isNotBlank(features)) {
            return url.substring(url.lastIndexOf(features) + features.length(), url.length());
        }
        return null;
    }

    /**
     * 获取文件名
     * @param filename
     * @return
     */
    public String getName(String filename) {
        if (StringUtil.isNotBlank(filename)) {
            return filename.substring(0, filename.lastIndexOf(".") - 1);
        }
        return null;
    }

    /**
     * 获取文件后缀
     * @param filename
     * @return
     */
    public String getSuffix(String filename) {
        if (StringUtil.isNotBlank(filename)) {
            return filename.substring(filename.lastIndexOf("."), filename.length());
        }
        return null;
    }

    /**
     *
     * @param file
     */
    public void responseFile(File file, OutputStream out) {
        FileInputStream in = null;

        try {
            in =  new FileInputStream(file);
            StreamUtils.copyRange(in, out, 0, in.available());
            out.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
                if (out != null) {
                    out.close();
                }
            } catch (IOException ex) {
            }
        }
    }

    /**
     *
     * @param type
     * @param name
     */
    public void responseFileByName(String type, String name, OutputStream out) {
        File file = this.getFile(type, name);
        this.responseFile(file, out);
    }

    /**
     * 文件复制
     * 采用二进制缓冲流来实现文件的读写
     * @param srcFile
     * @param destFile
     * @throws IOException
     */
    public static void fileCopy(File srcFile, File destFile) throws IOException {
        InputStream src = new BufferedInputStream(new FileInputStream(srcFile));
        OutputStream dest = new BufferedOutputStream(new FileOutputStream(destFile));

        byte[] buf = new byte[1024];

        int count = -1;

        while ((count = src.read(buf)) != -1) {
            dest.write(buf, 0, count);
        }
        dest.flush();
        src.close();
        dest.close();
    }

    /**
     * 备份文件，在原文件目录下创建备份文件， 原文件名.bak
     * @param filename
     * @return
     */
    public static boolean backupFile(String filename) {
        boolean flag = true;

        File srcFile = new File(filename);
        if (!srcFile.exists()) {
            System.err.println("目标文件不存在");
            return false;
        }

        // 创建备份文件
        File backupFile = new File(filename + BACKUP_SUFFIX);
        try {
            if (backupFile.createNewFile()) {
                fileCopy(srcFile, backupFile);
            }
        } catch (IOException ex) {
            flag = false;
            System.err.println("备份文件失败");
        }
        return flag;
    }

    /**
     * 恢复备份文件
     * @param backupFileName
     */
    public static void restoreFile(String backupFileName) {

        File srcFile = new File(backupFileName);
        if (!srcFile.exists()) {
            System.err.println("目标文件不存在");
            return;
        }

        String restore = backupFileName.substring(0, backupFileName.lastIndexOf(BACKUP_SUFFIX) - 1);
        File destFile = new File(restore);
        try {
            if (destFile.createNewFile()) {
                fileCopy(srcFile, destFile);
            }
        } catch (IOException ex) {
            System.err.println("恢复文件失败");
        }
    }
}
